# Copyright (c) 2025, qiushike and contributors
# For license information, please see license.txt

import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import getdate, flt


class SubcontractingServicePrice(Document):
	def validate(self):
		"""验证委外单价表数据"""
		self.validate_duplicate_price()
		self.validate_date_range()
		self.validate_step_price_items()
	
	def validate_duplicate_price(self):
		"""校验是否存在相同公司+供应商+物料号+工序且日期范围重叠的委外单价数据"""
		# 基本过滤条件：相同公司、供应商、物料号、工序，排除当前记录
		filters = {
			"company": self.company,
			"supplier": self.supplier,
			"item_code": self.item_code,
			"operation": self.operation,
			"name": ["!=", self.name]
		}
		
		# 查询符合基本条件的记录
		existing_prices = frappe.get_all(
			"Subcontracting Service Price",
			filters=filters,
			fields=["name", "from_date", "to_date"]
		)
		
		# 检查日期范围是否重叠
		for price in existing_prices:
			# 如果现有记录没有日期范围限制（即适用于所有日期）
			if not price.from_date and not price.to_date:
				frappe.throw(_(
					"A Subcontracting Service Price already exists for the same Company, Supplier, Item Code and Operation "
					"with no date restrictions. Reference: {0}"
				).format(price.name))
			
			# 如果当前记录没有日期范围限制（即适用于所有日期）
			if not self.from_date and not self.to_date:
				frappe.throw(_(
					"Cannot create a record with no date restrictions as another record exists for the same Company, "
					"Supplier, Item Code and Operation. Reference: {0}"
				).format(price.name))
			
			# 检查日期范围是否重叠
			date_overlap = False
			
			# 如果现有记录只有开始日期
			if price.from_date and not price.to_date:
				# 如果当前记录只有结束日期，且结束日期 >= 现有记录的开始日期
				if not self.from_date and self.to_date and getdate(self.to_date) >= getdate(price.from_date):
					date_overlap = True
				# 如果当前记录有开始日期，且开始日期 >= 现有记录的开始日期
				elif self.from_date and getdate(self.from_date) >= getdate(price.from_date):
					date_overlap = True
				# 如果当前记录有完整日期范围，且结束日期 >= 现有记录的开始日期
				elif self.from_date and self.to_date and getdate(self.to_date) >= getdate(price.from_date):
					date_overlap = True
			
			# 如果现有记录只有结束日期
			elif not price.from_date and price.to_date:
				# 如果当前记录只有开始日期，且开始日期 <= 现有记录的结束日期
				if self.from_date and not self.to_date and getdate(self.from_date) <= getdate(price.to_date):
					date_overlap = True
				# 如果当前记录有结束日期，且结束日期 <= 现有记录的结束日期
				elif self.to_date and getdate(self.to_date) <= getdate(price.to_date):
					date_overlap = True
				# 如果当前记录有完整日期范围，且开始日期 <= 现有记录的结束日期
				elif self.from_date and self.to_date and getdate(self.from_date) <= getdate(price.to_date):
					date_overlap = True
			
			# 如果现有记录有完整的日期范围
			elif price.from_date and price.to_date:
				# 检查是否有任何形式的重叠
				# 情况1：当前记录的开始日期在现有记录的日期范围内
				if self.from_date and getdate(price.from_date) <= getdate(self.from_date) <= getdate(price.to_date):
					date_overlap = True
				# 情况2：当前记录的结束日期在现有记录的日期范围内
				elif self.to_date and getdate(price.from_date) <= getdate(self.to_date) <= getdate(price.to_date):
					date_overlap = True
				# 情况3：当前记录的日期范围完全包含现有记录的日期范围
				elif self.from_date and self.to_date and getdate(self.from_date) <= getdate(price.from_date) and getdate(self.to_date) >= getdate(price.to_date):
					date_overlap = True
				# 情况4：当前记录的日期范围完全被现有记录的日期范围包含
				elif self.from_date and self.to_date and getdate(self.from_date) >= getdate(price.from_date) and getdate(self.to_date) <= getdate(price.to_date):
					date_overlap = True
			
			if date_overlap:
				frappe.throw(_(
					"A Subcontracting Service Price already exists for the same Company, Supplier, Item Code and Operation "
					"with overlapping date range. Reference: {0}"
				).format(price.name))
	
	def validate_date_range(self):
		"""校验开始日期不能晚于结束日期"""
		if self.from_date and self.to_date:
			if getdate(self.from_date) > getdate(self.to_date):
				frappe.throw(_("From Date cannot be after To Date"))
	
	def validate_step_price_items(self):
		"""校验委外阶梯明细的最小数量和最大数量"""
		if not self.subcontracting_step_price_item:
			return
		
		# 按最小数量排序
		sorted_items = sorted(self.subcontracting_step_price_item, key=lambda x: flt(x.min_qty))
		
		# 首先处理最后一行的空最大数量
		if sorted_items and len(sorted_items) > 0:
			last_item = sorted_items[-1]
			if not last_item.max_qty or flt(last_item.max_qty) == 0:
				last_item.max_qty = 999999999
		
		# 检查每一行
		for i, item in enumerate(sorted_items):
			# 检查最小数量是否小于最大数量
			if flt(item.min_qty) >= flt(item.max_qty):
				frappe.throw(_("Row #{0}: Min Qty ({1}) must be less than Max Qty ({2})").format(
					item.idx, item.min_qty, item.max_qty
				))
			
			# 检查与上一行的连续性
			if i > 0:
				prev_item = sorted_items[i - 1]
				if flt(item.min_qty) != flt(prev_item.max_qty):
					frappe.throw(_("Row #{0}: Min Qty ({1}) must be equal to Max Qty ({2}) of Row #{3}").format(
						item.idx, item.min_qty, prev_item.max_qty, prev_item.idx
					))


@frappe.whitelist()
def get_subcontracting_price(company, supplier, qty, item_code, operation, price_date=None):
	"""
	获取委外单价
	
	参数:
		company: 公司
		supplier: 供应商
		qty: 数量
		item_code: 物料号
		operation: 工序
		price_date: 价格日期（可选，默认为当前日期）
	
	返回:
		委外单价
	"""
	# 如果未提供日期，使用当前日期
	if not price_date:
		price_date = frappe.utils.today()
	
	# 转换为日期对象
	price_date = getdate(price_date)
	
	# 基本过滤条件
	filters = {
		"company": company,
		"supplier": supplier,
		"item_code": item_code,
		"operation": operation,
		"docstatus": 0  # 草稿状态
	}
	
	# 查询符合基本条件的记录
	price_records = frappe.get_all(
		"Subcontracting Service Price",
		filters=filters,
		fields=["name", "price", "from_date", "to_date"]
	)
	
	if not price_records:
		return 0
	
	# 筛选适用于指定日期的价格记录
	valid_price_records = []
	for record in price_records:
		# 情况1：无日期限制
		if not record.from_date and not record.to_date:
			valid_price_records.append(record)
			continue
		
		# 情况2：只有开始日期
		if record.from_date and not record.to_date:
			if getdate(record.from_date) <= price_date:
				valid_price_records.append(record)
				continue
		
		# 情况3：只有结束日期
		if not record.from_date and record.to_date:
			if price_date <= getdate(record.to_date):
				valid_price_records.append(record)
				continue
		
		# 情况4：有完整日期范围
		if record.from_date and record.to_date:
			if getdate(record.from_date) <= price_date <= getdate(record.to_date):
				valid_price_records.append(record)
				continue
	
	if not valid_price_records:
		return 0
	
	# 如果有多个有效记录，按照优先级排序：
	# 1. 有完整日期范围的记录
	# 2. 只有开始日期的记录
	# 3. 只有结束日期的记录
	# 4. 无日期限制的记录
	def sort_key(record):
		if record.from_date and record.to_date:
			return 1
		elif record.from_date and not record.to_date:
			return 2
		elif not record.from_date and record.to_date:
			return 3
		else:
			return 4
	
	valid_price_records.sort(key=sort_key)
	
	# 获取优先级最高的记录
	price_record = frappe.get_doc("Subcontracting Service Price", valid_price_records[0].name)
	
	# 先检查是否有阶梯价格
	if price_record.subcontracting_step_price_item:
		# 按最小数量排序
		sorted_items = sorted(price_record.subcontracting_step_price_item, key=lambda x: flt(x.min_qty))
		
		# 第一行特殊处理（左闭右闭）
		first_item = sorted_items[0]
		if flt(first_item.min_qty) <= flt(qty) <= flt(first_item.max_qty):
			return first_item.price
		
		# 其余行遵循左开右闭原则
		for i in range(1, len(sorted_items)):
			item = sorted_items[i]
			if flt(item.min_qty) < flt(qty) <= flt(item.max_qty):
				return item.price
	
	# 如果没有匹配的阶梯价格，返回表头价格
	if price_record.price:
		return price_record.price
	
	# 如果都没有，返回0
	return 0
